#ifndef xpack_concurrency_process
#define xpack_concurrency_process
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::concurrency_process::inc
#include"dumb/disable_copy.hpp"
#include"interface/seqptr.hpp"
#include"lang/cxx.hpp"
#include"macro/xdefer.hpp"
#include"macro/xforward.hpp"
#include"meta/has_cast.hpp"
#pragma pop_macro("xuser")

namespace mixc::concurrency_process::origin{
    enum class process_mode_t{
        pipe_none,
        pipe_write_only,
        pipe_read_only,
        pipe_read_write,
    };

    xstruct(
        xname(process),
        xpubb(inc::disable_copy),
        xprif(m_pid, ixx),
        xprif(m_tx, ixx),
        xprif(m_rx, ixx)
    )
        constexpr process() :
            m_pid(0),
            m_tx(0),
            m_rx(0){
        }

        constexpr process(process && self) :
            m_pid(self.m_pid),
            m_tx(self.m_tx),
            m_rx(self.m_rx){

            self.m_pid  = 0;
            self.m_tx   = 0;
            self.m_rx   = 0;
        }

        ~process();

        template<class ... args_t>
        requires(... and inc::has_cast<inc::c08, args_t>)
        bstate_t open(inc::c08 const & cmd_path, process_mode_t mode, args_t && ... cmd_list) const {
            // 注意：inc::c08 list[] 不能以 nullptr 结尾，因为 inc::c08(nullptr) 实际上并不是指向 nullptr，而是空串
            constexpr auto cmd_length = sizeof...(cmd_list);
            inc::c08 list[cmd_length + 1] = { xforward(cmd_list)... };
            return this->open_core(cmd_path, mode, list, cmd_length);
        }

        template<class ... args_t>
        requires(... and inc::has_cast<inc::c08, args_t>)
        bstate_t open(inc::c08 const & cmd_path, args_t && ... cmd_list) const {
            // 注意：inc::c08 list[] 不能以 nullptr 结尾，因为 inc::c08(nullptr) 实际上并不是指向 nullptr，而是空串
            constexpr auto cmd_length = sizeof...(cmd_list);
            inc::c08 list[cmd_length + 1] = { xforward(cmd_list)... };
            return this->open_core(cmd_path, process_mode_t::pipe_none, list, cmd_length);
        }

        template<class item_t>
        uxx read(inc::seqptr<item_t> seq) const {
            return this->read(seq, seq->length * sizeof(item_t));
        }

        template<class item_t>
        uxx write(inc::seqptr<item_t> seq) const {
            return this->write(seq, seq->length * sizeof(item_t));
        }

        uxx read(voidp buffer, uxx bytes)           const;
        uxx write(const void * buffer, uxx bytes)   const;
        i32 wait_exit()                             const;

    private:
        bstate_t open_core(inc::c08 const & cmd_path, process_mode_t mode, const inc::c08 cmd_list[], uxx cmd_length) const;
    $
}

#endif

xexport_space(mixc::concurrency_process::origin)
